<style scoped lang="scss">
.main {
  padding: 2vh;
  background-color: #2d3748;
}
.n-card {
  width: 20vw;
}
.n-slider {
  margin-top: 2vh;
}
.coordinate {
  margin-top: 2vh;
}
.n-input-number {
  width: 8vw;
}
.n-input {
  margin-top: 1vh;
}
</style>
<template>
  <div class="main">
    <n-flex justify="space-around" size="large">
      <div>
        <n-scrollbar style="max-height: 96vh">
          <canvas ref="canvas" width="1371" height="1920" :style="canvasStyle"></canvas>
        </n-scrollbar>
      </div>
      <div>
        <n-card>
          <n-switch v-model:value="isDrawingEnabled" :rail-style="railStyle">
            <template #checked>开启绘画</template>
            <template #unchecked>调整绘画</template>
          </n-switch>
          <n-space vertical>
            <n-slider v-model:value="value" :step="1" @update:value="handleSwitchChange" />
          </n-space>
        </n-card>
        <n-card style="margin-top: 3vh">
          <n-flex justify="space-between">
            <n-a href="/dot" > 点画框 </n-a>
            <n-a href="/line"> 拖动画框 </n-a>
            <n-a href="/surface" > 指定画框 </n-a>
          </n-flex>
        </n-card>
        <n-card style="margin-top: 3vh">
          <div class="coordinate">
            <n-input
              placeholder="音频名称"
              v-for="(shape, shapeIndex) in coordinates"
              :allow-input="onlyAllowAudio"
              :key="shapeIndex"
              :status="inputStatuses[shapeIndex]"
              :value="inputValues[shapeIndex]"
              @mouseenter="handleMouseEnter(shapeIndex)"
              @mouseleave="handleMouseLeave(shapeIndex)"
              @update:value="(val: string) => (inputValues[shapeIndex] = val)"
            >
              <template #prefix>
                <n-icon>
                  <ChatboxOutline />
                </n-icon>
              </template>
              <template #suffix>
                <n-button text style="font-size: 15px">
                  <n-icon @click="playAudio(shapeIndex)">
                    <PlayOutline />
                  </n-icon>
                </n-button>
              </template>
            </n-input>
          </div>
        </n-card>
      </div>
    </n-flex>
  </div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import type { CSSProperties } from 'vue'
import graphicalData from '@/store/tool/graphicalData'
import { ChatboxOutline, PlayOutline } from '@vicons/ionicons5'

import { storeToRefs } from 'pinia'
const appGaphicalData = graphicalData()
const { new_graphica } = storeToRefs(appGaphicalData)
const onlyAllowAudio = (value: string) => !value || /^[A-Za-z0-9._]+$/.test(value)

const value = ref(100)
const isDrawingEnabled = ref(true) // true: 绘画模式，false: 调整模式
const hoveredShapeIndex = ref<number | null>(null)

const railStyle = ({ focused, checked }: { focused: boolean; checked: boolean }): CSSProperties => {
  const style: CSSProperties = {}
  if (checked) {
    style.background = '#2080f0'

    if (focused) {
      style.boxShadow = '0 0 0 2px #2080f040'
    }
  } else {
    style.background = '#d03050'
    if (focused) {
      style.boxShadow = '0 0 0 2px #d03050'
    }
  }
  return style
}

const canvasStyle = computed(() => ({
  backgroundImage: '',
  transform: `scale(${value.value / 100})`,
  transformOrigin: 'top center'
}))

// 引用画布和上下文
const canvas = ref<HTMLCanvasElement | null>(null)
let ctx: CanvasRenderingContext2D | null = null

// 画图状态变量
const isDrawing = ref(false)
const startX = ref(0)
const startY = ref(0)

// 形状数组
type Shape = {
  points: { x: number; y: number }[]
  isSelected: boolean
}

const shapes = ref<Shape[]>([]) // 存储所有形状
let currentShape: Shape | null = null

// 坐标数组
const coordinates = new_graphica.value
// 判断音频是否可用
const inputStatuses = ref<string[]>(Array(coordinates.length).fill('')) // 默认状态为 warning
const inputValues = ref<string[]>(Array(coordinates.length).fill('')) // 默认状态为 warning

const playAudio = (index: number) => {
  const newUrl = 'http://192.168.0.166:3345/src/assets/audio/Unit_1/' + inputValues.value[index]
  console.log(newUrl)
  const audio = new Audio(newUrl)
  audio
    .play()
    .then(() => {
      inputStatuses.value[index] = 'success'
    })
    .catch((error) => {
      inputStatuses.value[index] = 'error'
    })
}
//缩放预览时 退出绘画模式
function handleSwitchChange() {
  if (isDrawingEnabled.value) {
    isDrawingEnabled.value = false
  }
}
// 调整形状的变量
const isDragging = ref(false)
let dragStartX = 0
let dragStartY = 0
let selectedShape: Shape | null = null

// 预加载背景图像
let backgroundImage: HTMLImageElement | null = null
const backgroundImageLoaded = ref(false)

onMounted(() => {
  if (canvas.value) {
    ctx = canvas.value.getContext('2d')

    // 预加载背景图像
    backgroundImage = new Image()
    backgroundImage.src = 'http://192.168.0.166:8084/image/1.png'
    backgroundImage.onload = () => {
      backgroundImageLoaded.value = true
      // 初始绘制
      drawAllShapes()
    }

    // 获取并初始化图形数据
    if (new_graphica.value) {
      shapes.value = new_graphica.value.map((shape) => ({
        points: shape.points, // 保留原有点位坐标
        isSelected: false // 初始化 isSelected 属性
      }))
      drawAllShapes() // 绘制所有形状
    }

    // 添加鼠标事件监听器
    canvas.value.addEventListener('mousedown', handleMouseDown)
    canvas.value.addEventListener('mousemove', handleMouseMove)
    window.addEventListener('mouseup', handleMouseUp)
    canvas.value.addEventListener('mouseout', handleMouseUp)
    // 防止右键菜单弹出
    canvas.value.addEventListener('contextmenu', handleContextMenu)
  }
})

onBeforeUnmount(() => {
  if (canvas.value) {
    canvas.value.removeEventListener('mousedown', handleMouseDown)
    canvas.value.removeEventListener('mousemove', handleMouseMove)
    window.removeEventListener('mouseup', handleMouseUp)
    canvas.value.removeEventListener('mouseout', handleMouseUp)
    canvas.value.removeEventListener('contextmenu', handleContextMenu)
  }
})

// 处理右键菜单事件，防止默认行为
function handleContextMenu(event: MouseEvent) {
  event.preventDefault()
}

// 更新 coordinates
function updateCoordinates() {
  coordinates.value = shapes.value.map((shape, shapeIndex) => ({
    shapeIndex,
    points: shape.points.map((point) => ({ x: point.x, y: point.y }))
  }))
  appGaphicalData.graphicaValue(coordinates.value)
}

// 处理鼠标按下事件
function handleMouseDown(event: MouseEvent) {
  const rect = canvas.value!.getBoundingClientRect()
  const mouseX = event.clientX - rect.left
  const mouseY = event.clientY - rect.top

  if (isDrawingEnabled.value && event.button === 0) {
    // 绘画模式
    isDrawing.value = true
    startX.value = mouseX
    startY.value = mouseY
    currentShape = { points: [{ x: startX.value, y: startY.value }], isSelected: false }
  } else if (!isDrawingEnabled.value) {
    if (event.button === 0) {
      // 调整模式 - 左键点击拖动
      // 检查鼠标是否在形状上
      selectedShape = getShapeAtPoint(mouseX, mouseY)
      if (selectedShape) {
        isDragging.value = true
        selectedShape.isSelected = true
        dragStartX = mouseX
        dragStartY = mouseY
      } else {
        // 取消选择所有形状
        shapes.value.forEach((shape) => (shape.isSelected = false))
      }
      drawAllShapes()
    } else if (event.button === 2) {
      // 调整模式 - 右键点击删除形状
      event.preventDefault()
      const shapeToDelete = getShapeAtPoint(mouseX, mouseY)
      if (shapeToDelete) {
        shapes.value = shapes.value.filter((shape) => shape !== shapeToDelete)
        drawAllShapes()
        // 更新坐标
        updateCoordinates()
      }
    }
  }
}

// 处理鼠标移动事件
function handleMouseMove(event: MouseEvent) {
  const rect = canvas.value!.getBoundingClientRect()
  const mouseX = event.clientX - rect.left
  const mouseY = event.clientY - rect.top

  if (isDrawingEnabled.value && isDrawing.value) {
    // 绘画模式
    if (currentShape) {
      currentShape.points.push({ x: mouseX, y: mouseY })
      drawAllShapes()
      drawCurrentShape()
    }
  } else if (!isDrawingEnabled.value && isDragging.value && selectedShape) {
    // 调整模式 - 拖动
    const dx = mouseX - dragStartX
    const dy = mouseY - dragStartY

    // 移动形状的所有点
    selectedShape.points = selectedShape.points.map((point) => ({
      x: point.x + dx,
      y: point.y + dy
    }))

    // 更新拖动起始位置
    dragStartX = mouseX
    dragStartY = mouseY

    drawAllShapes()
    // 更新坐标
    updateCoordinates()
  }
}
function handleMouseEnter(shapeIndex: number) {
  //鼠标移入时相应图形背景色变为半透明绿色
  hoveredShapeIndex.value = shapeIndex
  drawAllShapes()
}
function handleMouseLeave(shapeIndex: number) {
  //鼠标移出时变为透明色
  hoveredShapeIndex.value = null
  drawAllShapes()
}
// 处理鼠标抬起事件
function handleMouseUp(event: MouseEvent) {
  if (isDrawingEnabled.value && isDrawing.value) {
    // 绘画模式
    isDrawing.value = false
    if (currentShape) {
      // 连接到起点，闭合形状
      currentShape.points.push({ x: startX.value, y: startY.value })
      shapes.value.push(currentShape)
      currentShape = null
      drawAllShapes()
      // 更新坐标
      updateCoordinates()
    }
  } else if (!isDrawingEnabled.value && isDragging.value) {
    // 调整模式
    isDragging.value = false
    if (selectedShape) {
      selectedShape.isSelected = false
      selectedShape = null
      drawAllShapes()
      // 更新坐标
      updateCoordinates()
    }
  }
}

// 绘制所有形状
function drawAllShapes() {
  if (ctx && canvas.value) {
    // 清除画布
    ctx.clearRect(0, 0, canvas.value.width, canvas.value.height)

    // 绘制背景图像（如果已加载）
    if (backgroundImageLoaded.value && backgroundImage) {
      ctx.drawImage(backgroundImage, 0, 0, canvas.value.width, canvas.value.height)
    }

    // 绘制所有形状
    shapes.value.forEach((shape, index) => {
      drawShape(shape, index)
    })

    // 如果当前正在绘制形状，也绘制出来
    if (currentShape) {
      drawCurrentShape()
    }
  }
}

// 绘制当前正在绘制的形状
function drawCurrentShape() {
  if (ctx && currentShape) {
    ctx.beginPath()
    const points = currentShape.points
    ctx.moveTo(points[0].x, points[0].y)
    for (let i = 1; i < points.length; i++) {
      ctx.lineTo(points[i].x, points[i].y)
    }
    // 连接到起点
    ctx.lineTo(startX.value, startY.value)
    ctx.strokeStyle = 'green'
    ctx.lineWidth = 2
    ctx.stroke()
    ctx.closePath()
  }
}

// 绘制单个形状
function drawShape(shape: Shape, index: number) {
  if (ctx) {
    ctx.beginPath()
    const points = shape.points
    ctx.moveTo(points[0].x, points[0].y)
    for (let i = 1; i < points.length; i++) {
      ctx.lineTo(points[i].x, points[i].y)
    }
    ctx.closePath()

    // 设置样式
    // ctx.strokeStyle = shape.isSelected ? 'red' : 'green'
    ctx.strokeStyle = hoveredShapeIndex.value === index ? 'rgba(0, 255, 0, 0.5)' : 'red'
    ctx.lineWidth = 2
    ctx.fillStyle = hoveredShapeIndex.value === index ? 'rgba(0, 255, 0, 0.5)' : 'transparent'

    // 绘制形状
    ctx.fill()
    ctx.stroke()
  }
}

// 获取给定点上的形状
function getShapeAtPoint(x: number, y: number): Shape | null {
  for (let i = shapes.value.length - 1; i >= 0; i--) {
    const shape = shapes.value[i]
    if (isPointInShape(x, y, shape)) {
      return shape
    }
  }
  return null
}

// 检查点是否在形状内
function isPointInShape(x: number, y: number, shape: Shape): boolean {
  if (ctx) {
    ctx.beginPath()
    const points = shape.points
    ctx.moveTo(points[0].x, points[0].y)
    for (let i = 1; i < points.length; i++) {
      ctx.lineTo(points[i].x, points[i].y)
    }
    ctx.closePath()
    return ctx.isPointInPath(x, y)
  }
  return false
}
</script>
